package at.fhj.itm11.forum.data.impl;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import at.fhj.itm11.forum.data.RatingDAO;
import at.fhj.itm11.forum.model.Post;
import at.fhj.itm11.forum.model.Rating;

@Named
@Stateless
public class RatingDAOImpl implements RatingDAO {
	
	@Inject
	private EntityManager em;
	
	public Rating findById(Long id) {
		return em.find(Rating.class, id);
	}

	public Rating findRatingByRaterAndPost(Long userId, Long postId) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Rating> criteria = cb.createQuery(Rating.class);
		Root<Rating> rating = criteria.from(Rating.class);

		criteria.select(rating).where(cb.equal(rating.get("user"), userId), cb.equal(rating.get("post"), postId));
		return em.createQuery(criteria).getSingleResult();
	}

	public Long findPositiveRatingCountForPost(Long postId) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Long> criteria = cb.createQuery(Long.class);

		Root<Rating> rating = criteria.from(Rating.class);
		criteria.select(cb.count(rating));
		criteria.where(cb.equal(rating.get("post"), postId), cb.equal(rating.get("positiveRating"), true));
		return em.createQuery(criteria).getSingleResult();
	}

	public Long findNegativeRatingCountForPost(Long postId) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Long> criteria = cb.createQuery(Long.class);

		Root<Rating> rating = criteria.from(Rating.class);
		criteria.select(cb.count(rating));
		criteria.where(cb.equal(rating.get("post"), postId),cb.equal(rating.get("positiveRating"), false));
		return em.createQuery(criteria).getSingleResult();
	}

	@Override
	public void rate(Rating r) {
    	Post associatedPost = r.getPost();
    	Rating ratingFromDb;
    	
    	try {
    		ratingFromDb = findRatingByRaterAndPost(r.getUser().getId(), associatedPost.getId());
    		//update rating in database
    		ratingFromDb.setPositiveRating(r.isPositiveRating());
    		em.merge(ratingFromDb);
    	}catch(NoResultException ex) {
    		//insert rating in database
        	r.setPost(associatedPost);
        	em.persist(r);
    	}

	}

	public void setEm(EntityManager em) {
		this.em = em;
	}
}
